package com.detrum.detrumdata.newd;

import com.detrum.base.BaseStatic;
import com.detrum.base.ServiceStatic;
import com.detrum.bean.ViewPagerItem;
import com.detrum.detrumdata.R;
import com.detrum.detrumdata.service.USBConnetService;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;


public class DProtocol {
	private volatile static DProtocol dProtool;
	private USBConnetService usbconn;

	private static String upgrade_file ;
	private static String upgrade_file_version ;

	private int  D_FRAME_HEART_BREAT = 0;

	private final int  D_FRAME_ACK = 1;
	private final int  D_FRAME_NACK_WITH_CODE = 2;

	private final int  D_FRAME_GET_VERSION = 0x10;
	private final int  D_FRAME_VERSION_REPORT = 0x11;
	private final int  D_FRAME_DOWNLOAD_UPGRADE_FILE = 0x12;
	private final int  D_FRAME_STORE_FILE = 0x13;
	private final int  D_FRAME_ACTIVE_VER = 0x14;

	private final int D_FRAME_IWS_CONNECTED = 0x20;
	private final int D_FRAME_IWS_DISCONNECTED = 0x21;

	//for Android Mobile

	public static final int max_packet_length = 8 * 1024 ;

	public static final int D_FRAME_DEVICE_TYPE_VERSION_REPORT = 3;  //10位后面是两个字符串  每个\0结尾
	public static final int D_FRAME_DEVICE_BATTERY_PERCENT = 4;      //10位后面是1个字节，   百分比
	public static final int D_FRAME_IWS_CHANNEL_REPORT = 0x25;       //10位后面是1个字节     通道编码
	public static final int D_FRAME_ANDROID_ACCESSORY_ATTACHED = 0xf0;
	public static final int D_FRAME_ANDROID_START_VIDEO_TRANS = 0xF1;
	public static final int D_FRAME_ANDROID_STOP_VIDEO_TRANS = 0xf2;
	public static final int D_FRAME_VI_RESOLUTION_RATE = 0xf3;       //3个无符号 16 bit 整数， 宽，高，帧率

	private RandomAccessFile file_in = null;
	private long upgrade_file_len;
	private int current_offset;
	private int last_pack_len;

	private DprotocolCall dprotocolCall;

	public interface DprotocolCall{
		void disconnected();
		void channel(int channel);
		void uavInfo(ViewPagerItem uav_o);
		void battery(int battery);
		void deviceUpdate(int position);
		void videoResolution(int width,int height,int fps);
	}

    public DProtocol(USBConnetService conn){
		if(dProtool == null){
			dProtool = this;
		}
		usbconn = conn;
	}

	public String getFileMD5(String filePath) {
		try {
			File file = new File(filePath);
			FileInputStream fis = new FileInputStream(file);
			MessageDigest md = MessageDigest.getInstance("MD5");
			byte[] buffer = new byte[1024];
			int length = -1;
			while ((length = fis.read(buffer, 0, 1024)) != -1) {
				md.update(buffer, 0, length);
			}
			BigInteger bigInt = new BigInteger(1, md.digest());
			return bigInt.toString(16);
	
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return null;
	}

	public boolean fileIsExists(String filePath){
		try{
			File f=new File(filePath);
			if(!f.exists()){
				return false;
			}        
		}catch (Exception e) {
			// TODO: handle exception
			return false;
		}
		return true;
	}

	public long getFileSize(String filePath){
		try{
			File f=new File(filePath);
			if(!f.exists()){
				return -1;
			}
			return f.length();
		}catch (Exception e) {
			// TODO: handle exception
			return -1;
		}
	}
	//检查是否存在文件--存在即发送指令更新
	private void do_dprotocol_check_upgrade(){
		upgrade_file = BaseStatic.deviceLocalPath;
		upgrade_file_version = BaseStatic.deviceNetVersion;
		if(fileIsExists(upgrade_file) == false)
		{
			BaseStatic.savaInfoToSD("No upgrade file found!没有找到文件");
			return;
		}
		int datalen = 4 + 16*2 + upgrade_file_version.length() ;
		upgrade_file_len  = getFileSize(upgrade_file);
		String md5sum = getFileMD5(upgrade_file);
		int i;

		byte[]  msg = new byte[datalen+ + 2 + 2 + 8];
		msg[8] = 0; //seq 
		msg[9] = D_FRAME_DOWNLOAD_UPGRADE_FILE;		//download upgrade file

		//msg data len
		msg[10] = (byte)((datalen >> 8) & 0xFF);
		msg[11] = (byte)(datalen & 0xFF);

		//file len
		msg[12] = (byte)((upgrade_file_len >> 24) & 0xFF);
		msg[13] = (byte)((upgrade_file_len >> 16) & 0xFF);
		msg[14] = (byte)((upgrade_file_len >> 8) & 0xFF);
		msg[15] = (byte)(upgrade_file_len & 0xFF);

		int pad_len = 32 - md5sum.length();
		for(i=0;i<pad_len;i++)
		{
			msg[16+i] = '0';
		}
		System.arraycopy(md5sum.getBytes(), 0, msg,16+pad_len, md5sum.length());
		System.arraycopy(upgrade_file_version.getBytes(), 0, msg,48, upgrade_file_version.length());

		DFrame.genDFrameHeader(msg, msg.length, DFrameEntity.DFRAME_ENTITY_MOBILE_DEVICE,
			DFrameEntity.DFRAME_ENTITY_IWT_GS, DFrameType.DFRAME_TYPE_DPROTOCOL,
			datalen + 4);
		BaseStatic.savaInfoToSD("开始更新文件");
		usbconn.SendToUsb(msg,0,datalen + 4 + 8);
	}

	private Runnable checkupgradeRunnable = new Runnable() {
    @Override
	public void run() {
		try {
               	do_dprotocol_check_upgrade();
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        }
    };

	public void setDprotocolCall(DprotocolCall dprotocolCall){
		this.dprotocolCall = dprotocolCall;
	}

	public void dprotocol_check_upgrade(){
		Thread upgradeThread;
		upgradeThread = new Thread(checkupgradeRunnable);
		upgradeThread.start();
	}

	private int d_frame_send_upgrade_file(){
		byte[] msg_body = null;
		int pack_len ;
		if(file_in == null){
			try {
				file_in = new RandomAccessFile(upgrade_file, "r");
			}
			catch (IOException e) {
				e.printStackTrace();
			}
			current_offset = 0;
			last_pack_len = 0;
		}
		try {
			file_in.seek(current_offset);
		}
		catch (IOException e) {
			e.printStackTrace();
		}

		if( (upgrade_file_len - current_offset) < max_packet_length ){
			pack_len = (int)upgrade_file_len - current_offset;
		}else{
			pack_len = max_packet_length;
		}
		last_pack_len = pack_len;

		msg_body = new byte[pack_len + 8 + 2 + 2 + 4];

		msg_body[8] = 0;					//seq
		msg_body[9] = D_FRAME_STORE_FILE;	//msg_id

		msg_body[10] = (byte) ( (pack_len >> 8) & 0xFF );
		msg_body[11] = (byte) ( pack_len & 0xFF );

		msg_body[12] = (byte) ( (current_offset >> 24) & 0xFF );
		msg_body[13] = (byte) ( (current_offset >> 16) & 0xFF );
		msg_body[14] = (byte) ( (current_offset >> 8) & 0xFF );
		msg_body[15] = (byte) ( current_offset & 0xFF );

		if(current_offset + pack_len < upgrade_file_len) {
				msg_body[12] =  (byte)( msg_body[12] | (byte)(0x80) );
		}

		try {
			file_in.read(msg_body,16,pack_len);
		}
		catch (IOException e) {
			e.printStackTrace();
		}

		DFrame.genDFrameHeader(msg_body, msg_body.length, DFrameEntity.DFRAME_ENTITY_MOBILE_DEVICE,
			DFrameEntity.DFRAME_ENTITY_IWT_GS, DFrameType.DFRAME_TYPE_DPROTOCOL,
			pack_len + 2 + 2 + 4);
		BaseStatic.savaInfoToSD("更新文件校验");
		usbconn.SendToUsb(msg_body,0,pack_len + 2 + 2 + 4 + 8);
		return 0;
	}
	//激活
	private int d_frame_active_version(){
		byte[] msg_body = null;
		
		msg_body = new byte[8 + upgrade_file_version.length()+1 + 2 + 2];

		msg_body[8] = 0;					//seq
		msg_body[9] = D_FRAME_ACTIVE_VER;	//msg_id==判断case

		msg_body[10] = (byte) ( (upgrade_file_version.length() >> 8) & 0xFF );
		msg_body[11] = (byte) ( upgrade_file_version.length() & 0xFF );

		System.arraycopy(upgrade_file_version.getBytes(), 0, msg_body, 8+4, upgrade_file_version.length());

		msg_body[ 8 + upgrade_file_version.length() + 2 + 2] = 0x0;

		DFrame.genDFrameHeader(msg_body, msg_body.length, DFrameEntity.DFRAME_ENTITY_MOBILE_DEVICE,
			DFrameEntity.DFRAME_ENTITY_IWT_GS, DFrameType.DFRAME_TYPE_DPROTOCOL,
			upgrade_file_version.length()+1 + 2 + 2 );
		BaseStatic.savaInfoToSD("获取版本");
		usbconn.SendToUsb(msg_body,0,upgrade_file_version.length() +1 + 2 + 2 + 8);
		return 0;
	}

	//连接后接收信息
	public int dprotocol_input(byte[] buff, int offset, int len){
		if(len < 2){
			return -1;
		}
		byte command = buff[offset + 1];
		switch(command){
			case D_FRAME_IWS_CONNECTED: //0x20   连接成功
				break;

			case D_FRAME_IWS_DISCONNECTED:  //0x21  连接断开
				dprotocolCall.disconnected();
				break;

			case D_FRAME_ACK:  //1  版本更新
				dprotocol_ack_process(buff,offset+2,len-2);
				break;

			case D_FRAME_DEVICE_BATTERY_PERCENT: // 4 电量信息
				dprotocol_battery_process(buff,offset+2,len-2);
				break;

			case D_FRAME_DEVICE_TYPE_VERSION_REPORT: // 3  版本信息
				dprotocol_version_process(buff,offset+2,len-2);
				break;

			case D_FRAME_IWS_CHANNEL_REPORT: //0x25  信道信息
				dprotocol_channel_process(buff,offset+2,len-2);
				break;

			case (byte)D_FRAME_VI_RESOLUTION_RATE: //0xf3  录像尺寸和帧率
				dprotocol_resolution_process(buff,offset+2,len-2);
				break;

		}
		return 0;
	}

	private void dprotocol_resolution_process(byte[] buff, int i, int i1) {
		ServiceStatic.recordWidth = (buff[i]<<8&0xff00) + (buff[i+1]&0xff);
		ServiceStatic.recordHeight = (buff[i+2]<<8&0xff00) + (buff[i+3]&0xff);
		ServiceStatic.recordFps = (buff[i+4]<<8&0xff00) + (buff[i+5]&0xff);
		BaseStatic.savaInfoToSD("DProtocol ------ "+ServiceStatic.recordWidth+"------"+ServiceStatic.recordHeight+"------"+ServiceStatic.recordFps);
	}

	//版本更新
	private int dprotocol_ack_process(byte[] buff, int offset, int len){
		byte msg_id = buff[offset];
		BaseStatic.savaInfoToSD("Dprotocol msg_id = "+msg_id);
		switch(msg_id){
			case D_FRAME_DOWNLOAD_UPGRADE_FILE:
				BaseStatic.savaInfoToSD("Start to Send Upgrade File 设备下载文件");
				dprotocolCall.deviceUpdate(1);
				d_frame_send_upgrade_file();
				break;

			case D_FRAME_STORE_FILE:
				//检查文件的完整性
				current_offset += last_pack_len;
				if(current_offset<upgrade_file_len) {
					BaseStatic.savaInfoToSD("Start to Send Upgrade File again 设备检测文件完整性");
					d_frame_send_upgrade_file();
					dprotocolCall.deviceUpdate(2);
				} else{
					BaseStatic.savaInfoToSD("Finished Sending Upgrade File 设备文件下载完成");
					d_frame_active_version();
					dprotocolCall.deviceUpdate(3);
				}
				break;

			case D_FRAME_ACTIVE_VER:
				dprotocolCall.deviceUpdate(4);
				BaseStatic.savaInfoToSD("Active Upgrade File Success 新版本激活成功");
				File file=new File(upgrade_file);
				if(file.exists()){
					file.delete();
					BaseStatic.savaInfoToSD("file is delete 删除更新文件");
				}
				break;
		}
		return 0;
	}
	//获取信道信息
	private void dprotocol_channel_process(byte[] buff, int i, int i1) {
		byte msg = buff[i];
		int x=msg&0xff;
		Integer[]ints={x};
		//EventBus.getDefault().post(ints);
		dprotocolCall.channel(x);
	}
	//获取版本号和设备信息
	private void dprotocol_version_process(byte[] buff, int i, int len) {
		byte[] msg=new byte[len];
		System.arraycopy(buff, i, msg, 0, len);
		int x=0;
		for (int j = 0; j < len-1; j++) {
			if(msg[j]==0x00){
				x=j;
			}
		}
		byte[] msg1=new byte[x],msg2=new byte[len-x];

		System.arraycopy(msg, 0, msg1, 0, x);
		System.arraycopy(msg, x, msg2, 0, len-x);

		BaseStatic.deviceUsbName = new String(msg1).trim();
		BaseStatic.deviceUsbVersion = new String(msg2).trim();
		String DeviceName = new String(msg1);
		String DeviceVersion = new String(msg2);
		BaseStatic.savaInfoToSD(DeviceName);
		BaseStatic.savaInfoToSD(DeviceVersion);

		ViewPagerItem uav_o=new ViewPagerItem();
		uav_o.setName(DeviceName.trim());
		uav_o.setMsg(DeviceVersion.trim());
		if(DeviceName.contains("IWT")){
			uav_o.setImage(R.mipmap.mslogo);
		}
		if(dprotocolCall!=null){
			dprotocolCall.uavInfo(uav_o);
			dprotocolCall.deviceUpdate(5);
		}
	}
	//获取电池信息
	private void dprotocol_battery_process(byte[] buff, int offset, int len) {
		byte msg = buff[offset];
		int x=msg&0xff;
		dprotocolCall.battery(x);
	}

}
